/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.bizentity.webapi;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.StringDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.TreeTraversingParser;
import com.inspur.edp.bef.bemanager.befexception.BeManagerException;
import com.inspur.edp.bef.bemanager.codegenerator.JavaCodeFileGenerator;
import com.inspur.edp.bef.bemanager.compcodebutton.CompPathButton;
import com.inspur.edp.bef.bemanager.compcodebutton.GenerateCompCodeButton;
import com.inspur.edp.bef.bemanager.generatecomponent.ComponentGenUtil;
import com.inspur.edp.bef.bemanager.generatecomponent.ComponentGenerator;
import com.inspur.edp.bef.bemanager.generatecomponent.componentgenerators.TccActionComponentGenerator;
import com.inspur.edp.bef.bemanager.generatedbo.GenerateFromDbo;
import com.inspur.edp.bef.bemanager.pushchangesetevent.PushChangeSetEventBroker;
import com.inspur.edp.bef.bemanager.service.BeManagerService;
import com.inspur.edp.bef.bemanager.service.BusinessFieldService;
import com.inspur.edp.bef.bemanager.service.ImportCdmService;
import com.inspur.edp.bef.bemanager.service.UpdateElementCollectionService;
import com.inspur.edp.bef.bemanager.util.BeGuideUtil;
import com.inspur.edp.bef.bemanager.util.CheckComUtil;
import com.inspur.edp.bef.bemanager.util.CheckInfoUtil;
import com.inspur.edp.bef.bemanager.util.DataValidatorUtil;
import com.inspur.edp.bef.bemanager.util.DboUtil;
import com.inspur.edp.bef.bizentity.GspBizEntityElement;
import com.inspur.edp.bef.bizentity.GspBizEntityObject;
import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.bef.bizentity.beenum.BEOperationType;
import com.inspur.edp.bef.bizentity.common.OperationConvertUtils;
import com.inspur.edp.bef.bizentity.json.element.BizElementDeserializer;
import com.inspur.edp.bef.bizentity.json.element.BizElementSerializer;
import com.inspur.edp.bef.bizentity.json.model.BizEntityDeserializer;
import com.inspur.edp.bef.bizentity.json.model.BizEntitySerializer;
import com.inspur.edp.bef.bizentity.json.object.BizObjectDeserializer;
import com.inspur.edp.bef.bizentity.json.object.BizObjectSerializer;
import com.inspur.edp.bef.bizentity.json.operation.*;
import com.inspur.edp.bef.bizentity.operation.BizOperation;
import com.inspur.edp.bef.bizentity.operation.Determination;
import com.inspur.edp.bef.bizentity.operation.Validation;
import com.inspur.edp.bef.bizentity.operation.internalmgraction.TccSettingElement;
import com.inspur.edp.bef.bizentity.pushchangesetargs.PushChangeSet;
import com.inspur.edp.bef.bizentity.pushchangesetargs.PushChangeSetArgs;
import com.inspur.edp.bef.bizentity.pushchangesetargs.RelatedMetadata;
import com.inspur.edp.bef.bizentity.util.ReferenceService;
import com.inspur.edp.bef.bizentity.util.StringUtil;
import com.inspur.edp.bef.bizentity.util.changeset.ChangeSetInfoUtil;
import com.inspur.edp.bef.component.base.GspComponent;
import com.inspur.edp.cef.designtime.api.IGspCommonDataType;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.element.GspElementDataType;
import com.inspur.edp.cef.designtime.api.json.Variable.CommonVariableDeserializer;
import com.inspur.edp.cef.designtime.api.json.Variable.CommonVariableSerializer;
import com.inspur.edp.cef.designtime.api.json.operation.CommonDtmDeserializer;
import com.inspur.edp.cef.designtime.api.operation.CommonDetermination;
import com.inspur.edp.cef.designtime.api.operation.CommonValidation;
import com.inspur.edp.cef.designtime.api.variable.CommonVariable;
import com.inspur.edp.das.commonmodel.IGspCommonElement;
import com.inspur.edp.das.commonmodel.IGspCommonModel;
import com.inspur.edp.das.commonmodel.IGspCommonObject;
import com.inspur.edp.das.commonmodel.collection.GspElementCollection;
import com.inspur.edp.das.commonmodel.entity.object.GspCommonObjectType;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.entity.MetadataHeader;
import com.inspur.edp.lcm.metadata.api.entity.ProcessMode;
import com.inspur.edp.lcm.metadata.api.service.FileService;
import com.inspur.edp.lcm.metadata.api.service.MetadataProjectService;
import com.inspur.edp.lcm.metadata.api.service.MetadataService;
import io.iec.edp.caf.common.JSONSerializer;
import io.iec.edp.caf.commons.exception.ExceptionLevel;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.regex.Matcher;
import java.util.stream.Collectors;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import io.iec.edp.caf.rpc.api.service.RpcClient;
import lombok.Data;
import lombok.SneakyThrows;

@Path("")
@Produces(MediaType.APPLICATION_JSON)
public class BeController {

    private final String  EXCEPTIONCODE= "BeCodeGenController";
    /**
     * BE保存并同步，同步dbo,生成构件元数据，构件代码模板，保存元数据
     * @param metadataInfo
     */
    @Path("sysnbe")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public boolean saveAndSyn(String metadataInfo) {
        JsonNode node = getNodeFromWebJson(metadataInfo);

        isMetadataCodeExist(node);

        String path = node.get("path").textValue();
        String metadataName = node.get("name").textValue();
        boolean enableApproval = false;
        GspMetadata metadata = SpringBeanUtils.getBean(MetadataService.class).loadMetadata(metadataName, path);
        //校验元数据主子节点编号
        GspBusinessEntity businessEntity = (GspBusinessEntity) metadata.getContent();
        if(businessEntity.getMainObject().getContainChildObjects()!=null && businessEntity.getMainObject().getContainChildObjects().size()>0){
            for(IGspCommonObject object : businessEntity.getMainObject().getContainChildObjects()){
                if(object.getCode()!=null && object.getCode().equals(businessEntity.getMainObject().getCode())){
                    throw new RuntimeException("BE元数据["+metadata.getHeader().getName()+"]上的主对象与子对象编号重复，请修改对象编号。重复编号：["+object.getCode()+"]");
                }
            }
        }
        //预置基础入口单据的RPC接口
        enableApproval = BeGuideUtil.getInstance().precastFlowFormPayload(metadata);
        // 主节点添加UDT字段
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        BeManagerService.generateDbo(metadata, path, true);
        ArrayList<String> actionList=BeManagerService.generateComponent(metadata, path, false);

        if(actionList != null && actionList.size() >0 && BeManagerService.getProjectProcessMode(path) == ProcessMode.interpretation) {
            BeManagerService.generatePom(path, businessEntity.getName());
        }
        BeManagerService.generateComponentCode(metadata, path,actionList);
        BeManagerService.saveMetadata(metadata, path);
        ReferenceService.getInstance().registerReference(metadata);
        return enableApproval;
    }

    @Path("checkBizTypeState")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public boolean checkBizTypeState(String boId) {
        return BeGuideUtil.getInstance().bizObjectContainBizType(boId);
    }

    public JsonNode getNodeFromWebJson(String json) {

        ObjectMapper mapper = new ObjectMapper();
        JsonNode node = null;

        try {
            node = mapper.readTree(json);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("json串解析失败！");
        }
        return node;
    }

    /**
     * 选择业务字段
     * @param info
     * @return
     */
    @Path("chooseUdt")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String updateUdtElementWhenChooseUdt(String info) {
        JsonNode node = getNodeFromWebJson(info);
        String refUdtId = node.get("refUdtId").textValue();
        String path = node.get("path").textValue();
        String beElementJson = node.get("udtElementJson").textValue();

        return UpdateElementCollectionService.getInstance().updateElementWithRefUdt(refUdtId, path, beElementJson, true);
    }

    @Path("updateUdt")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String updateUdtElementWhenLoading(String info) {
        JsonNode node = getNodeFromWebJson(info);
        String refUdtId = node.get("refUdtId").textValue();
        String path = node.get("path").textValue();
        String beElementJson = node.get("udtElementJson").textValue();

        return UpdateElementCollectionService.getInstance().updateElementWithRefUdt(refUdtId, path, beElementJson, false);
    }

    @Path("handleRefElement")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String hanldeRefElement(String info) {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(IGspCommonField.class, new BizElementSerializer());
        module.addDeserializer(IGspCommonField.class, new BizElementDeserializer());
        mapper.registerModule(module);
        JsonNode node = getNodeFromWebJson(info);
        String beElementJson = node.get("udtElementJson").textValue();
        GspBizEntityElement entityElement;
        String eleJosn;
        try {
            entityElement = mapper.readValue(beElementJson, GspBizEntityElement.class);
            UpdateElementCollectionService.getInstance().updateFieldWithAsso(null, entityElement);
            eleJosn = mapper.writeValueAsString(entityElement);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

        return eleJosn;
    }

    /**
     * 同步业务字段
     * @param info
     * @return
     */
    @Path("handleElements")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public boolean handleElements(String info) {
        JsonNode node = getNodeFromWebJson(info);
        String fileName = node.get("fileName").textValue();
        String path = node.get("path").textValue();
        String nodeCode = node.get("nodeCode") != null ? node.get("nodeCode").textValue() : null;
        GspMetadata metadata = SpringBeanUtils.getBean(MetadataService.class).loadMetadata(fileName, path);

        GspBusinessEntity beEntity = (GspBusinessEntity) metadata.getContent();
        ArrayList<IGspCommonElement> elements = nodeCode == null ? beEntity.getAllElementList(false)
            : beEntity.findObjectByCode(nodeCode).getAllElementList(false);
        //先后有区别：先更新udt,后更新关联
        UpdateElementCollectionService.getInstance().handleUdtElements(path, elements);
        UpdateElementCollectionService.getInstance().handleRefElements(path, elements);
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(GspBusinessEntity.class, new BizEntitySerializer());
        module.addDeserializer(IGspCommonModel.class, new BizEntityDeserializer());
        mapper.registerModule(module);
        String eleJosn;
        GspBusinessEntity businessEntity;
        try {
            eleJosn = mapper.writeValueAsString((GspBusinessEntity) metadata.getContent());
            businessEntity = mapper.readValue(eleJosn, GspBusinessEntity.class);
            metadata.setContent(businessEntity);
            BeManagerService.saveMetadata(metadata, path);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

        return true;
    }

    @Path("handleBusinessField")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String hanldeBusinessField(String info) {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(IGspCommonField.class, new BizElementSerializer());
        module.addDeserializer(IGspCommonField.class, new BizElementDeserializer());
        mapper.registerModule(module);

        BusinessFieldService businessFieldService = new BusinessFieldService();
        GspBizEntityElement bizEntityElement = businessFieldService.handelElements(info);
        String json = null;
        try {
            json = mapper.writeValueAsString(bizEntityElement);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return json;
    }

    /**
     * 变量选择业务字段
     *
     * @param info
     * @return
     */
    @Path("chooseVarUdt")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String updateVarUdtElementWhenChooseUdt(String info) {
        JsonNode node = getNodeFromWebJson(info);
        String refUdtId = node.get("refUdtId").textValue();
        String path = node.get("path").textValue();
        String beElementJson = node.get("udtElementJson").textValue();

        return UpdateElementCollectionService.getInstance().updateVariableWithRefUdt(refUdtId, path, beElementJson, true);
    }

    @Path("updateVarUdt")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String updateVarUdtElementWhenLoading(String info) {
        JsonNode node = getNodeFromWebJson(info);
        String refUdtId = node.get("refUdtId").textValue();
        String path = node.get("path").textValue();
        String beElementJson = node.get("udtElementJson").textValue();

        return UpdateElementCollectionService.getInstance().updateVariableWithRefUdt(refUdtId, path, beElementJson, false);
    }

    @Path("handleRefVariable")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String hanldeRefVariable(String info) {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(IGspCommonField.class, new CommonVariableSerializer());
        module.addDeserializer(IGspCommonField.class, new CommonVariableDeserializer());
        mapper.registerModule(module);
        JsonNode node = getNodeFromWebJson(info);
        String beElementJson = node.get("udtElementJson").textValue();
        CommonVariable commonVariable;
        String eleJosn;
        try {
            commonVariable = mapper.readValue(beElementJson, CommonVariable.class);
            UpdateElementCollectionService.getInstance().updateFieldWithAsso(null, commonVariable);
            eleJosn = mapper.writeValueAsString(commonVariable);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

        return eleJosn;
    }

    @Path("uploadCdm")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String uploadCdm(String info) {
        JsonNode node=getNodeFromWebJson(info);
        String xml = node.get("xml").textValue();
        return ImportCdmService.getInstance().convertToJson(xml);
    }
    @Path("convertCdmTableToBizElements")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String convertCdmTableToBizElements(String info) {
        JsonNode node=getNodeFromWebJson(info);
        String columnsJson = node.get("columnsJson").textValue();
        return ImportCdmService.getInstance().convertCdmTableToBizElements(columnsJson);
    }

    /**
     * 创建BE元数据，根据DBO创建
     * @param info
     * @return
     */
    @Path("convertDboToBizEntity")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String convertDboToBizEntity(String info) {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(IGspCommonModel.class, new BizEntitySerializer());
        module.addDeserializer(IGspCommonModel.class, new BizEntityDeserializer());
        mapper.registerModule(module);
        try {
            JsonNode node = mapper.readTree(info);
            String path = node.get("path").textValue();
            String dboId = node.get("dboId").textValue();
            String primaryKey = node.get("primaryKey").textValue();
            String beJson = node.get("content").textValue();
            DataValidatorUtil.CheckForEmptyString(path, "path");
            DataValidatorUtil.CheckForEmptyString(dboId, "dboId");
            DataValidatorUtil.CheckForEmptyString(primaryKey, "primaryKey");
            DataValidatorUtil.CheckForEmptyString(beJson, "当前BE");
            GspBusinessEntity newBe = mapper.readValue(beJson, GspBusinessEntity.class);

            GspBizEntityObject mainObj = GenerateFromDbo.getInstance().convertDboToBizObject(path, dboId, primaryKey);
            mainObj.setCode(newBe.getCode());
            mainObj.setName(newBe.getName());
            mainObj.setObjectType(GspCommonObjectType.MainObject);
            newBe.setMainObject(mainObj);
            // 处理版本字段
            newBe.getVersionContronInfo().setVersionControlElementId(null);
            if (mainObj.getElementByLabelId("Version") instanceof IGspCommonElement) {
                if (mainObj.getElementByLabelId("Version").getMDataType() == GspElementDataType.DateTime) {
                    newBe.getVersionContronInfo().setVersionControlElementId(mainObj.getElementByLabelId("Version").getID());
                }
            }
            return mapper.writeValueAsString(newBe);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("GspBusinessEntity序列化反序列化失败！");
        }

    }

    /**
     * 根据dbo子对象创建BE子对象
     * @param info
     * @return
     */
    @Path("addDboToParentObject")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String addDboToParentObject(String info) {

        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(IGspCommonDataType.class,new BizObjectSerializer());
        module.addDeserializer(IGspCommonDataType.class,new BizObjectDeserializer());
        mapper.registerModule(module);
        try {
        JsonNode node = mapper.readTree(info);
        String path = node.get("path").textValue();
        String dboId = node.get("dboId").textValue();
            String columnIdsJson = node.get("columnIdsJson").textValue();
        String primaryKey = node.get("primaryKey").textValue();
        String parentId = node.get("parentId").textValue();
        String parentObjectIdElementId = node.get("parentObjectIdElementId").textValue();
        String parentObjectIdElementName = node.get("parentObjectIdElementName").textValue();
        String newChildObjCode = node.get("newChildObjCode").textValue();
        String newChildObjName = node.get("newChildObjName").textValue();
        
        GspBizEntityObject childObject = convertDboToChildObj(path,dboId,primaryKey,parentId,parentObjectIdElementId,parentObjectIdElementName);
        handleCheckedColumns(childObject, columnIdsJson, primaryKey, parentId);
        handleChildObjectCodeName(childObject, newChildObjCode, newChildObjName);

        String objJson=mapper.writeValueAsString(childObject);
        return objJson;
    } catch (JsonProcessingException e) {
        throw new RuntimeException("GspBusinessEntity序列化失败！"+e);
    }

}


    private void handleChildObjectCodeName(GspBizEntityObject childObject, String newChildObjCode, String newChildObjName) {
        if (!CheckInfoUtil.checkNull(newChildObjCode))
        {
            childObject.setCode(newChildObjCode);
        }
        if (!CheckInfoUtil.checkNull(newChildObjName))
        {
            childObject.setName(newChildObjName);
        }
    }

    private GspBizEntityObject convertDboToChildObj(String path, String dboId, String primaryKey, String parentId, String parentObjectIdElementId, String parentObjectIdElementName) {
        GspBizEntityObject childObject = GenerateFromDbo.getInstance().convertDboToBizObject(path, dboId, primaryKey);
        childObject.setObjectType(GspCommonObjectType.ChildObject);
        GspBizEntityElement parentElement = (GspBizEntityElement) childObject.getContainElements().stream().filter(item -> ((IGspCommonElement)item).getColumnID().equals(parentId)).findFirst().orElse(null);
        if (parentElement == null)
        {
            throw new BeManagerException("",EXCEPTIONCODE, "当前设置的ParentID列在dbo上不存在。",null, ExceptionLevel.Error,false);
        }
        childObject.convertToChildObject(parentElement.getID(), parentObjectIdElementId, parentObjectIdElementName);
        return childObject;
    }

    private void handleCheckedColumns(GspBizEntityObject childObject, String columnIdsJson, String primaryKey, String parentId) {
        List<String> ids =readIdList(columnIdsJson);
        if (ids==null||ids.size()==0)
        {
            return;
        }
        if (ids.size() > 0)
        {
            if (!ids.contains(primaryKey))
            {
                throw new BeManagerException("",EXCEPTIONCODE, "当前未选中主键字段。",null,ExceptionLevel.Error,false);
            }
            if (!ids.contains(parentId))
            {
                throw new BeManagerException("",EXCEPTIONCODE, "当前未选中ParentID字段。",null,ExceptionLevel.Error,false);
            }
            GspElementCollection elements = childObject.getContainElements().clone(childObject, null);
            childObject.getContainElements().clear();
            childObject.getContainElements().addAll(elements.stream().filter(item -> ids.contains(((IGspCommonElement)item).getColumnID())).collect(Collectors.toList()));
    }
    }

    private List<String> readIdList(String beEleIds) {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module=new SimpleModule();
        module.addDeserializer(String.class,new StringDeserializer());
        mapper.registerModule(module);
        JavaType type = mapper.getTypeFactory().
                constructCollectionType(List.class, String.class);
        List<String> ids=null;
        try {
            ids=mapper.readValue(beEleIds,type);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("id列表反序列化失败"+e);
        }
        return ids;
    }
    /**
     *
     * @param info
     * @return
     */
    @Path("addDboColumns")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String addDboColumns(String info) {

        ObjectMapper mapper=new ObjectMapper();
        SimpleModule module=new SimpleModule();
        module.addSerializer(IGspCommonField.class,new BizElementSerializer());
        module.addDeserializer(IGspCommonField.class,new BizElementDeserializer());
        mapper.registerModule(module);
        try {
            JsonNode node =mapper.readTree(info);
            String path =node.get("path").textValue();
            String dboId =node.get("dboId").textValue();
            String columnIdsJson =node.get("columnIdsJson").textValue();
            List<String> columnIds=readIdList(columnIdsJson);

            GspElementCollection elements=GenerateFromDbo.getInstance().ConvertDboColumnsToElements(path,dboId,columnIds,null);

            String elementJson=mapper.writeValueAsString(elements);
            return elementJson;
        } catch (JsonProcessingException e) {
            throw new RuntimeException("GspBusinessEntity序列化失败！");
        }
    }

    /**
     * 获取BE依赖的元数据（当前BO）
     * @param info
     * @return
     */
    @Path("getRefMetadataList")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String getRefMetadataList(String info) {
        ObjectMapper mapper=new ObjectMapper();
        JsonNode node = null;
        try {
            node = mapper.readTree(info);
            String metadataPath = node.get("metadataPath").textValue();
            String BizEntityId = node.get("BizEntityId").textValue();
            MetadataService metadataService = SpringBeanUtils.getBean(com.inspur.edp.lcm.metadata.api.service.MetadataService.class);
            List<GspMetadata> gspMetadataList = metadataService.getMetadataListByRefedMetadataId(metadataPath, BizEntityId);
            ArrayList<RelatedMetadata> infos = new ArrayList<>();
            gspMetadataList.stream().
                    forEach(item -> {
                        MetadataHeader header = item.getHeader();
                        if (item.getHeader().getType().equals("GSPViewModel")) {
                            infos.add(new RelatedMetadata(header.getNameSpace(),header.getCode(),header.getName(),"GSPViewModel"));
                        };
                    });
        String metadataListString = mapper.writeValueAsString(infos);
        return metadataListString;
        } catch (JsonProcessingException e) {
            throw new RuntimeException("序列化元数据信息失败", e);
        }
    }

    /**
     * 推送BE 变更集
     * @param info 变更内容
     */
    @Path("pushChangeSet")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public void pushChangeSet(JsonNode info) {
        PushChangeSet changeSet = ChangeSetInfoUtil.getChangeSetInfo(info);
        if(changeSet != null){
            PushChangeSetEventBroker pushEventBroker = SpringBeanUtils.getBean(PushChangeSetEventBroker.class);
            pushEventBroker.firePushChangeSet(new PushChangeSetArgs(changeSet));
        }
    }
    @Path("pushDataSet")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String pushDataSet(JsonNode info) {
        RpcClient client = SpringBeanUtils.getBean(RpcClient.class);
        String dataSetName = info.get("dataSetName").textValue();
        String metadataName = info.get("fileName").textValue();
        String relativePath = info.get("relativePath").textValue();
        GspMetadata metadata = SpringBeanUtils.getBean(MetadataService.class).loadMetadata(metadataName, relativePath);

        LinkedHashMap<String, Object> paramMap = new LinkedHashMap<String, Object>();
        paramMap.put("gspMetadata", metadata);
        String bizTypeId = BeGuideUtil.getInstance().getBizTypeId(metadata.getHeader().getBizobjectID());
        paramMap.put("productId", bizTypeId);
        paramMap.put("name",dataSetName);

        return client.invoke(String.class
                , "com.inspur.gs.gsp.qdp.qdpdatasetinfo.service.DatasetInfoInnerService.generateDataSetByBe"
                , "bcc", paramMap, null);
    }

    @Path("getDataSetInfoByBeId")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String getDataSetInfoByBeId(String beId) {
        RpcClient client = SpringBeanUtils.getBean(RpcClient.class);
        LinkedHashMap<String, Object> paramMap = new LinkedHashMap<String, Object>();
        paramMap.put("beId",beId);
        return client.invoke(String.class
                , "com.inspur.gs.gsp.qdp.qdpdatasetinfo.service.DatasetInfoInnerService.getDataSetInfoByBeId"
                , "bcc", paramMap, null);
    }


    /**
     * 获取BE动作构件代码
     * @param info
     * @return
     */
    @Path("bizOperationComponentCode")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String getBizOperationComponentCode(JsonNode info) {
        String id = info.get("metadataId").textValue();
        String projectpath = info.get("metadataPath").textValue();
        String type = info.get("actionType").textValue();
        String action = info.get("actionCode").textValue();
        ArrayList<String> actionList = new ArrayList<>();
        actionList.add(action);
        GspMetadata metadata = SpringBeanUtils.getBean(MetadataService.class).loadMetadataByMetadataId(id, projectpath);
        GspBusinessEntity be = (GspBusinessEntity) metadata.getContent();
        String relativePath = metadata.getRelativePath();
        String compAssemblyName = ComponentGenUtil.GetComponentNamespace(relativePath);

        GenerateCompCodeButton button = new GenerateCompCodeButton();
        String code =button.getCompCodeButton(be,type,relativePath,actionList,compAssemblyName);

        return code;
    }

    /**
     * 获取BE动作构件代码路径
     * @param info
     * @return
     */
    @Path("bizOperationComponentCodePath")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String getBizOperationComponentCodePath(JsonNode info) {
        String id = info.get("metadataId").textValue();
        String projectpath = info.get("metadataPath").textValue();
        String type = info.get("actionType").textValue();
        String action = info.get("actionCode").textValue();
        ArrayList<String> actionList = new ArrayList<>();
        actionList.add(action);
        GspMetadata metadata = SpringBeanUtils.getBean(MetadataService.class).loadMetadataByMetadataId(id, projectpath);
        GspBusinessEntity be = (GspBusinessEntity) metadata.getContent();
        String relativePath = metadata.getRelativePath();
        String compAssemblyName = ComponentGenUtil.GetComponentNamespace(relativePath);

        CompPathButton button = new CompPathButton();
        String filePath =button.getCompPath(be,type,relativePath,actionList,compAssemblyName);
        filePath.replaceAll("\\\\", Matcher.quoteReplacement(File.separator));
        filePath.replaceAll("/", Matcher.quoteReplacement(File.separator));
        return filePath;
    }

    @Path("eventComponentCodePath")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String getEventComponentCodePath(JsonNode info) {
        if(info.get("compMetaDataId") == null){
            throw new RuntimeException("compMetaDataId不能为空");
        }
        if(info.get("metadataPath") == null){
            throw new RuntimeException("metadataPath不能为空");
        }
        String compMetaDataId = info.get("compMetaDataId").textValue();
        if(compMetaDataId == null || "".equals(compMetaDataId)){
            throw new RuntimeException("compMetaDataId不能为空");
        }
        String projectpath = info.get("metadataPath").textValue();
        if(projectpath == null || "".equals(projectpath)){
            throw new RuntimeException("metadataPath不能为空");
        }
        GspMetadata compMetaData = SpringBeanUtils.getBean(MetadataService.class).getRefMetadata(projectpath, compMetaDataId);
        if(compMetaData == null){
            throw new RuntimeException("未加载到元数据，元数据id:" + compMetaDataId);
        }
        return BeManagerService.getCodePath(projectpath, compMetaData);
    }

    /**
     * 判断当前元数据是否在当前BO内
     * @param info
     * @return
     */
    @Path("isMetadataExist")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public boolean isMetadataExist(JsonNode info) {
        if(StringUtil.checkNull(info)) {
            return false;
        }
        String path = info.get("path").textValue();
        String metadataFileName = info.get("metadataFileName").textValue();
        MetadataService service = SpringBeanUtils.getBean(com.inspur.edp.lcm.metadata.api.service.MetadataService.class);
        return service.isMetadataExist(path, metadataFileName);
    }


    private void isMetadataCodeExist(JsonNode info) {
        if(StringUtil.checkNull(info)) {
            return;
        }
        String metadataName = info.get("name").textValue();
        String projectPath = info.get("path").textValue();

        GspMetadata metadata = SpringBeanUtils.getBean(MetadataService.class).loadMetadata(metadataName, projectPath);
        GspBusinessEntity be = (GspBusinessEntity) metadata.getContent();
        List<CheckComUtil> checkInfo = new ArrayList<>();
        getNewActions(be,checkInfo);
        CompPathButton button = new CompPathButton();
        String relativePath = metadata.getRelativePath();
        if(checkInfo.size()<=0){
            return;
        }
        for(CheckComUtil checkComUtil : checkInfo) {
            ArrayList<String> actionList = new ArrayList<>();
            actionList.add(checkComUtil.getAction());
            String filePath = button.getFilePath(be, checkComUtil.getType(), actionList, relativePath);
            FileService fsService = SpringBeanUtils.getBean(FileService.class);
            filePath.replaceAll("\\\\", Matcher.quoteReplacement(File.separator));
            filePath.replaceAll("/", Matcher.quoteReplacement(File.separator));
            if (fsService.isFileExist(filePath)) {
                button.JavaReplace(filePath);
//                throw new RuntimeException("BE元数据:"+be.getName()+"上新增的 "+checkComUtil.getChangeInfo()+checkComUtil.getAction()+" 已存在构件代码。请修改其编号或按路径删除旧java代码文件后，再执行保存。"+"\r\n代码路径："+filePath);
            }
        }
    }

    private void getNewActions(GspBusinessEntity be, List<CheckComUtil> checkInfo){
        for(BizOperation bizMgrAction : be.getCustomMgrActions()){
            if (bizMgrAction.getComponentId() == null||"".equals(bizMgrAction.getComponentId())) {
                CheckComUtil tem = new CheckComUtil();
                tem.setType("BizActions");
                tem.setAction(bizMgrAction.getCode());
                tem.setChangeInfo("对外接口方法");
                checkInfo.add(tem);
            }
        }
        for(GspBizEntityObject object : be.getAllNodes()) {
            for (BizOperation bizAction : object.getCustomBEActions()) {
                if (bizAction.getComponentId() == null||"".equals(bizAction.getComponentId())) {
                    CheckComUtil tem = new CheckComUtil();
                    tem.setType("EntityActions");
                    tem.setAction(bizAction.getCode());
                    tem.setChangeInfo("节点"+object.getName()+"的内部方法");
                    checkInfo.add(tem);
                }
            }
        }
        for(GspBizEntityObject object : be.getAllNodes()) {
            for (BizOperation determination : object.getDeterminations()) {
                if (determination.getComponentId() == null||"".equals(determination.getComponentId())) {
                    CheckComUtil tem = new CheckComUtil();
                    tem.setType("Determinations");
                    tem.setAction(determination.getCode());
                    tem.setChangeInfo("节点"+object.getName()+"的事件");
                    checkInfo.add(tem);
                }
            }
        }
        for(GspBizEntityObject object : be.getAllNodes()) {
            for (BizOperation validation : object.getValidations()) {
                if (validation.getComponentId() == null||"".equals(validation.getComponentId())) {
                    CheckComUtil tem = new CheckComUtil();
                    tem.setType("Validations");
                    tem.setAction(validation.getCode());
                    tem.setChangeInfo("对象"+object.getName()+"的校验规则");
                    checkInfo.add(tem);
                }
            }
        }
        for(GspBizEntityObject object : be.getAllNodes()) {
            for (TccSettingElement ele : object.getTccSettings()) {
                if (ele.getTccAction().getComponentId() == null||"".equals(ele.getTccAction().getComponentId())) {
                    CheckComUtil tem = new CheckComUtil();
                    tem.setType("TccActions");
                    tem.setAction(ele.getTccAction().getCode());
                    tem.setChangeInfo("节点"+object.getName()+"的TCC配置");
                    checkInfo.add(tem);
                }
            }
        }
        for(CommonDetermination dtm : be.getVariables().getDtmAfterModify()){
            if (dtm.getComponentId() == null||"".equals(dtm.getComponentId())) {
                CheckComUtil tem = new CheckComUtil();
                tem.setType("VarDeterminations");
                tem.setAction(dtm.getCode());
                tem.setChangeInfo("自定义变量联动计算");
                checkInfo.add(tem);
            }
        }
    }

    @SneakyThrows
    @Path("deletecompcode")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public void deleteCompAndCode(JsonNode node) {
        ArrayNode compIdsNode = (ArrayNode)Objects.requireNonNull(node.get("compIds"), "构件id列表不能为空");
        String path = Objects.requireNonNull(node.get("path"), "路径不能为空").textValue();
        List<String> compIds = new ArrayList<>(compIdsNode.size());
        compIdsNode.iterator().forEachRemaining(item -> compIds.add(Objects.requireNonNull(item.textValue(), "构件id不能为空")));

        MetadataProjectService projService = SpringBeanUtils.getBean(MetadataProjectService.class);
        MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);
        FileService fService = SpringBeanUtils.getBean(FileService.class);
        for (String compId : compIds) {
            if(!metadataService.isMetadataExistInProject(path, compId)){
                throw new RuntimeException("当前工程下不存在构件:" + compId );
            }
        }
        String compPath = projService.getJavaCompProjectPath(path);
        for (String compId : compIds) {
            GspMetadata compMetaData = metadataService.loadMetadataByMetadataId(compId, path);
            String javaClass = ((GspComponent) compMetaData.getContent()).getMethod().getClassName();
            javaClass = javaClass.replace(".", File.separator).concat(".java");
            String codePath = CheckInfoUtil.getCombinePath(compPath, javaClass);
            metadataService.deleteMetadata(compMetaData.getRelativePath(), compMetaData.getHeader().getFileName());
            if(fService.isFileExist(codePath)) {
                fService.fileDelete(codePath);
            }
        }
    }

    private FutureTask generatePomAsync(String path) {
        if(BeManagerService.getProjectProcessMode(path) != ProcessMode.interpretation) {
            return null;
        }
        Callable mc = () -> {
            BeManagerService.generatePom(path, path);
            return null;
        };

        FutureTask ft = new FutureTask(mc);

        Thread t1 = new Thread(ft);
        t1.start();
        return ft;
    }

    @SneakyThrows
    @Path("buildvarcompcode")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public BuildCompCodeResult createVariableCompAndCode(JsonNode node) {
        JsonNode beContent = node.get("beContent");
        String path = node.get("path").textValue();
        String bizObjectId = node.get("bizObjectId").textValue();
        JsonNode opContent = node.get("opContent");
        FutureTask pomFt = generatePomAsync(path);
        GspBusinessEntity be = JSONSerializer.getObjectMapper().readValue(
            new TreeTraversingParser(beContent), GspBusinessEntity.class);
        TreeTraversingParser opParser = new TreeTraversingParser(opContent);
        opParser.nextToken();
        CommonDetermination dtm = (CommonDetermination) new CommonDtmDeserializer()
            .deserialize(opParser, null);

        GspMetadata compMeta =  ComponentGenerator.getInstance().createCompByVarDtm(
            dtm, be, path, bizObjectId);
        dtm.setComponentId(compMeta.getHeader().getId());
        dtm.setComponentName(compMeta.getHeader().getCode());
        new JavaCodeFileGenerator(path, be).createVarDtmJavaCodeFile(dtm);
        String codePath = BeManagerService.getCodePath(path, compMeta);
        if(pomFt != null)
        pomFt.get();
        return new BuildCompCodeResult(compMeta.getHeader(), codePath);
    }

    @SneakyThrows
    @Path("buildtcccompcode")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public BuildCompCodeResult createTccCompAndCode(JsonNode node) {
        JsonNode beContent = node.get("beContent");
        String path = node.get("path").textValue();
        String bizObjectId = node.get("bizObjectId").textValue();
        String nodeCode = node.get("nodeCode").textValue();
        boolean isChild = node.get("isChild").booleanValue();
        JsonNode opContent = node.get("opContent");
        FutureTask pomFt = generatePomAsync(path);

        GspBusinessEntity be = JSONSerializer.getObjectMapper().readValue(
            new TreeTraversingParser(beContent), GspBusinessEntity.class);
        TreeTraversingParser opParser = new TreeTraversingParser(opContent);
        opParser.nextToken();
        TccSettingElement operation = new TccSettingElementDeserializer().deserialize(
            opParser, null);
        operation.setOwner(isChild ? (GspBizEntityObject) be.findObjectByCode(nodeCode) : be.getMainObject());
        operation.getTccAction().setOwner(operation.getOwner());

        GspMetadata compMeta = TccActionComponentGenerator.getInstance().createComponent(
            operation, path, bizObjectId , nodeCode);
        operation.getTccAction().setComponentId(compMeta.getHeader().getId());
        operation.getTccAction().setComponentName(compMeta.getHeader().getCode());
        new JavaCodeFileGenerator(path, be).createJavaCodeFile(operation.getTccAction(), isChild, nodeCode);
        String codePath = BeManagerService.getCodePath(path, compMeta);
        if(pomFt != null)
            pomFt.get();
        return new BuildCompCodeResult(compMeta.getHeader(), codePath);
    }

    @SneakyThrows
    @Path("builddtmcompcode")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public BuildCompCodeResult createDtmCompAndCode(JsonNode node) {
        JsonNode beContent = node.get("beContent");
        String path = node.get("path").textValue();
        String bizObjectId = node.get("bizObjectId").textValue();
        String nodeCode = node.get("nodeCode").textValue();
        boolean isChild = node.get("isChild").booleanValue();
        String triggerTimePointType = node.get("triggerTimePointType").textValue();
        JsonNode opContent = node.get("opContent");
        FutureTask pomFt = generatePomAsync(path);

        GspBusinessEntity be = JSONSerializer.getObjectMapper().readValue(
            new TreeTraversingParser(beContent), GspBusinessEntity.class);
        TreeTraversingParser jsonParser = new TreeTraversingParser(opContent);
        jsonParser.nextToken();
        CommonDetermination commonDtm = (CommonDetermination) new BizCommonDeterminationDeSerializer()
            .deserialize(jsonParser, null);

        Determination operation = OperationConvertUtils.convertToDtm(commonDtm, triggerTimePointType,
            isChild ? (GspBizEntityObject) be.findObjectByCode(nodeCode) : be.getMainObject());
        GspMetadata metadata = BeManagerService.createCompCode(path, bizObjectId, nodeCode, isChild, be, operation);
        String codePath = BeManagerService.getCodePath(path, metadata);
        if(pomFt != null)
            pomFt.get();
        return new BuildCompCodeResult(metadata.getHeader(), codePath);
    }

    @SneakyThrows
    @Path("buildvalcompcode")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public BuildCompCodeResult createValCompAndCode(JsonNode node) {
        JsonNode beContent = node.get("beContent");
        String path = node.get("path").textValue();
        String bizObjectId = node.get("bizObjectId").textValue();
        String nodeCode = node.get("nodeCode").textValue();
        boolean isChild = node.get("isChild").booleanValue();
        String triggerTimePointType = node.get("triggerTimePointType").textValue();
        JsonNode opContent = node.get("opContent");
        FutureTask pomFt = generatePomAsync(path);

        GspBusinessEntity be = JSONSerializer.getObjectMapper().readValue(
            new TreeTraversingParser(beContent), GspBusinessEntity.class);
        TreeTraversingParser jsonParser = new TreeTraversingParser(opContent);
        jsonParser.nextToken();
        CommonValidation commonOperation = (CommonValidation) new BizCommonValdationDeSerializer()
            .deserialize(jsonParser, null);
        Validation operation = OperationConvertUtils.convertToVal(commonOperation, triggerTimePointType,
            isChild ? (GspBizEntityObject) be.findObjectByCode(nodeCode) : be.getMainObject());
        GspMetadata metadata = BeManagerService.createCompCode(path, bizObjectId, nodeCode, isChild, be, operation);
        String codePath = BeManagerService.getCodePath(path, metadata);
        if(pomFt != null)
            pomFt.get();
        return new BuildCompCodeResult(metadata.getHeader(), codePath);
    }

    @SneakyThrows
    @Path("buildcompcode")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public BuildCompCodeResult createCompAndCode(JsonNode node) {
        JsonNode beContent = node.get("beContent");
        String path = node.get("path").textValue();
        String bizObjectId = node.get("bizObjectId").textValue();
        String nodeCode = node.get("nodeCode").textValue();
        boolean isChild = node.get("isChild").booleanValue();
        BEOperationType opType = Enum.valueOf(BEOperationType.class, node.get("opType").textValue());
        JsonNode opContent = node.get("opContent");
        FutureTask pomFt = generatePomAsync(path);

        GspBusinessEntity be = JSONSerializer.getObjectMapper().readValue(
            new TreeTraversingParser(beContent), GspBusinessEntity.class);
        BizOperation operation = deserializeOperation(opType, opContent);
        operation.setOwner(isChild ? (GspBizEntityObject) be.findObjectByCode(nodeCode) : be.getMainObject());

        //生成构件元数据
        GspMetadata metadata = BeManagerService.createCompCode(path, bizObjectId, nodeCode, isChild, be, operation);
        String codePath = BeManagerService.getCodePath(path, metadata);
        if(pomFt != null)
            pomFt.get();
        return new BuildCompCodeResult(metadata.getHeader(), codePath);
    }

    @SneakyThrows
    private static BizOperation deserializeOperation(BEOperationType opType, JsonNode op) {
        JsonDeserializer deserializer;
        switch (opType) {
            case Determination:
                deserializer = new BizDeterminationDeserializer();
                break;
            case Validation:
                deserializer = new BizValidationDeserializer();
                break;
            case BizMgrAction:
                deserializer = new BizMgrActionDeserializer();
                break;
            case BizAction:
                deserializer = new BizActionDeserializer();
                break;
            default:
                throw new RuntimeException("不支持动作类型" + opType);
        }
        TreeTraversingParser jsonParser = new TreeTraversingParser(op);
        jsonParser.nextToken();
        return (BizOperation) deserializer.deserialize(jsonParser, null);
    }

    @Data
    private class BuildCompCodeResult {
        public BuildCompCodeResult(MetadataHeader comp, String codePath) {
            this.comp = comp;
            this.codePath = codePath;
        }

        private MetadataHeader comp;
        private String codePath;
    }

    @SneakyThrows
    @Path("deleteObjectDbo")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public void deleteObjectDboFiles(JsonNode node) {
        ArrayNode dboIDSNode = (ArrayNode)Objects.requireNonNull(node.get("dboIDs"), "DBOID列表不能为空");
        String path = Objects.requireNonNull(node.get("path"), "路径不能为空").textValue();
        List<String> dboIDs = new ArrayList<>(dboIDSNode.size());
        dboIDSNode.iterator().forEachRemaining(item -> dboIDs.add(Objects.requireNonNull(item.textValue(), "构件id不能为空")));

        DboUtil.dealDboFiles(dboIDs, path);
    }
}
